perf(actionbars): skip the button build for bars that can never be shown - #2005
Merged
EllesmereGaming merged 1 commit intoSep 7, 2026
Merged
Conversation
A bar marked alwaysHidden (or disabled) still built all twelve of its secure buttons at load. Measured on a reload: 31 ms on a profile hiding four bars, and 16.5 ms on the default profile, where Bar9 and Bar10 ship hidden. Three readouts placed the cost. Per-bar setup is 95 % button creation, and 73 % of that is Blizzard's CreateFrame on the action button template. Nothing inside the loop is reducible - ForceButtonRefresh, the per-button GetCVarBool, the flyout registration and the childupdate snippets total 7.2 ms across 120 buttons - so the only lever is building fewer buttons. SetupBar now creates the bar frame and skips the button loop for a bar in the Never set, leaving barFrames[key] non-nil and barButtons[key] an empty table. The button half moved to ns.BuildBarButtons so the reveal edge can run it against the existing frame. RefreshRuntimeVisibility builds them the moment a bar leaves the Never set, re-runs the secure ref pass and the keybind rebuild, and defers the cosmetic apply by a frame. ns.IsNeverBar is now the single predicate for "can never be shown", read by both RecomputeNeverBars and the load-time skip, so the two cannot drift apart. LayoutBar's memo gained the actual button count. Its own comment claims every input the body reads folds into the stamp; the body reads buttons[i], and this change made that count variable at runtime, so a revealed bar hit an unchanged stamp and its buttons were never positioned. Load time on this profile: 164.9 ms -> 124.3 ms, ActionBars OnEnable 102.3 -> 62.8 ms.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Action bars that can never be shown -- Visibility set to Hidden, or the bar disabled -- no longer build their twelve action buttons at load. On a profile that hides four of the twelve bars this cuts total UI load time from 164.9 ms to 124.3 ms, and ActionBars' own share of it from 102.3 ms to 62.8 ms. On the default profile it saves about 16.5 ms for every user with no configuration at all, because Bar 9 and Bar 10 ship hidden.
The bar frame is still created, so nothing that looks up a bar frame changes; only the buttons are deferred. They are built the moment the bar leaves the hidden state, whether that comes from the Visibility dropdown, the Toggle Action Bar keybind, Show During Drag or Show When Spellbook Is Open, and the bar arrives complete with its keybinds and styling. Nothing about how a hidden or a visible bar behaves changes for the player.
Three profiling passes established that there is nothing cheaper available here. Per-bar setup is 95 % button creation, and 73 % of that is Blizzard's
CreateFrameon the action button template. All the remaining per-button work across all 120 buttons -- the visual refresh, the attribute writes, the flyout registration and the childupdate snippets -- adds up to 7.2 ms, so building fewer buttons is the only lever with real size behind it.Two supporting changes come with it.
ns.IsNeverBaris now the single predicate for "this bar can never become visible", read by bothRecomputeNeverBarsand the new load-time skip, so the two cannot drift apart. AndLayoutBar's memo stamp gained the actual button count: its own comment states that every input the body reads folds into the stamp, the body readsbuttons[i], and deferring the build made that count variable at runtime for the first time.How was it tested?
Tested in-game on live. Revealing a hidden bar from the Visibility dropdown brings it back immediately with all twelve buttons positioned, styled and bound, with no reload needed. Turning on Show During Drag for a bar still set to Hidden and then picking up a spell surfaces that bar with its buttons, and the drop lands on it. The load-time figures above are reload-to-reload measurements on the same character and profile, taken in one sitting.
Checklist
HookScript/hooksecurefunconly, neverSetScripton Blizzard frames -- the deferred buttons are the addon's own EABButtons built through the existing helper, and the stance and pet bars, which reuse Blizzard's buttons, are excluded from the change outright